Skip to content

Add 'mouse_entered', 'mouse_exited' and 'mouse_pressed' to Sprite2D and Polygon2D#114776

Open
Ezequias-Rodrigues wants to merge 38 commits intogodotengine:masterfrom
Ezequias-Rodrigues:master
Open

Add 'mouse_entered', 'mouse_exited' and 'mouse_pressed' to Sprite2D and Polygon2D#114776
Ezequias-Rodrigues wants to merge 38 commits intogodotengine:masterfrom
Ezequias-Rodrigues:master

Conversation

@Ezequias-Rodrigues
Copy link

@Ezequias-Rodrigues Ezequias-Rodrigues commented Jan 9, 2026

This PR improves mouse input handling for CanvasItem-based nodes by integrating _mouse_hit_test() into the input propagation path and emitting mouse-related signals directly from CanvasItem.

It enables accurate mouse interaction for 2D nodes without relying on physics.

Summary of changes

  • Added mouse hover and press signal emission to CanvasItem
  • mouse_entered_node
  • mouse_exited_node
  • mouse_pressed_node
  • Brought has_point() method up from control to canvas_Item, overriding it in sprite2d and polygon2d to be pixel perfect
  • Override input() from node in canvas_item to be able to call has_point()
  • Created a new toggle for CanvasItem, mouse_picking, which is set to false by default. It enables the mouse picking behavior when set to true.

Motivation

Currently, CanvasItem nodes receive mouse input in a decentralized way, requiring each node to manually perform hit tests, often using only bounding rectangles.

This PR:

  • Enables pixel-perfect and shape-aware interaction
  • Avoids physics-based picking for non-physical visuals
  • Aligns CanvasItem mouse behavior more closely with existing GUI patterns

Use cases

  • Pixel-perfect interaction for Sprite2D
  • Accurate picking for Polygon2D and Line2D
  • Lightweight 2D editors and tools
  • Interactive visuals that should not require physics bodies
  • My game, hehe

Compatibility

  • No impact on Control / GUI input handling
  • No physics or rendering changes
  • Needs to be enabled using set_process_input(true) AND set_mouse_picking(true), so won't affect older projects unless "opted in"

Notes

  • This PR does not introduce a new input system
  • It builds on existing input propagation and virtual hooks already present in CanvasItem
  • Designed to be minimal, efficient, and easy to extend

Ezequias Rodrigues added 7 commits January 6, 2026 15:13
Introduces a virtual _mouse_hit_test method in CanvasItem, overridden in Sprite2D and Polygon2D for accurate mouse interaction detection. Adds mouse_entered, mouse_exited, and mouse_pressed signals to Sprite2D and Polygon2D, and implements input event handling in CanvasItem to emit these signals based on mouse events. This enhances interactivity for 2D nodes by enabling per-item mouse event handling.
Updated CanvasItem::input to use global mouse position and improved mouse enter/exit signal logic. Removed debug print statements and made mouse_inside non-mutable for clarity.
@Ezequias-Rodrigues Ezequias-Rodrigues requested review from a team as code owners January 9, 2026 02:06
@AdriaandeJongh
Copy link
Contributor

what about performance? will this negatively impact nodes that don’t implement this feature?

@Ezequias-Rodrigues
Copy link
Author

Ezequias-Rodrigues commented Jan 9, 2026

The input function and _mouse_hit_test will only be called if input processing is set to true for a given node
So i don't think it will negatively impact nodes that makes no use of input(Unless the coder deliberately set input processing to true for every node or something like that)

Added a check in CanvasItem::input to return early if the item is not visible in the scene tree, preventing unnecessary input processing for hidden items.
@AThousandShips

This comment was marked as resolved.

@Ezequias-Rodrigues
Copy link
Author

Ezequias-Rodrigues commented Jan 9, 2026

Did you use AI to write this? If so you need to mention this

The PR contains strange random changes to unrelated files, and isn't valid C++ code, so it clearly hasn't been tested in the way it is written right now

I tried to use copilot at first, but got frustrated with it trying to override a inexistent function and decided to do the work myself.

At first i tried to change the scene tree because i wasn't understanding how input was being propragated but then i went to canvas item

I'll take a better look when i get to home, sorry for the mess, this is my first PR

@AThousandShips
Copy link
Member

AThousandShips commented Jan 9, 2026

Please test your code before opening a PR, making sure it compiles first of all but just making sure it actually does what you want it to do is a basic requirement (might have missed something but the code doesn't look like it compiles to me, but it doesn't seem to be tested with that in mind)

Did you intend to add the functionality to Line2D as well?

@Ezequias-Rodrigues
Copy link
Author

Ezequias-Rodrigues commented Jan 9, 2026

So, what makes the code fails is the styling(i took a time to read the logs, GHA / 📊 Static checks / Code style, file formatting, and docs (pull_request) is what is failing)

The code actually compiles, i've tested it before with a minimal script. The only thing i haven't tested, because was like the last thing i made before i went to sleep was the addition of the check if the node is visible or not, i had the idea right after reading the comment about performance.

And yes, i intended to edit line 2D, but haven't implemented yet because of laziness, if this PR goes thru, i'll take a better look at it(Being totally honest, polygon2d alone solves what i want to my game, i extended it to Sprite2D because seemed natural, and wanted Line2D but this one wasn't so straightforward)

@AThousandShips
Copy link
Member

Good then that was just a misunderstanding from the code, I meant there looked like there was some compile issues with the code (not from CI) so I asked

But this PR is not really in a good state for being ready it seems to be a work in progress, with all the unrelated changes and formatting

@Ezequias-Rodrigues
Copy link
Author

The unrelated file change is just a linebreak/whitespace. I tried changing scenetree to implement this, but after i discovered a better way to do it, i just deleted the function i was writing, and the linebreak/whitespace went unnoticed.
I'm fixing the styling rn, mostly whitespaces and tabs mixed. I'll pay closer attention to that in the future

@Ezequias-Rodrigues Ezequias-Rodrigues marked this pull request as draft January 9, 2026 13:07
Ezequias Rodrigues added 11 commits January 14, 2026 13:39
I must concede that i don't fully understand why this won't compile for android/ios, but it think it has something to do with canvasitem being a "friend class", i'll take a while to study this later. For now, i will just hotfix it, because the casting is not really necessary i think
@AThousandShips
Copy link
Member

Please do not push so many times in a row, you are a first time contributor so you need approval to run CI, but otherwise this would really take up a lot of CI processing and time, so please make your changes in a batch

@Ezequias-Rodrigues
Copy link
Author

Ok, i'm sorry, i wasn't paying attention to this PR actually
I think i'll have to make a branch in my fork, all commits i send there are mirrored here and i wasn't really expecting that. My bad

@Ezequias-Rodrigues
Copy link
Author

Ezequias-Rodrigues commented Jan 14, 2026

Ok, i've tested the code by hand, and all 20 automated checks were successfully in my branch

I'm sorry for the mess i created, i really wanted to help but was not really familiarized with how things are done.

I hope my contribution help someone, and thank you for the patience.

Also, newbie question: These commits that appeared after i merged my branch: are they ok? i was expecting that only the final one showed up here

@MarianoGnu
Copy link
Contributor

MarianoGnu commented Jan 14, 2026

you need to squash the 36 commits in a single one to be considered for merging, this can wait until it's reviewed, but is good practice to keep the PR clean

@Ezequias-Rodrigues Ezequias-Rodrigues marked this pull request as ready for review January 14, 2026 21:11
@Ezequias-Rodrigues Ezequias-Rodrigues requested a review from a team as a code owner January 14, 2026 21:11
@Saulo-de-Souza
Copy link
Contributor

I believe this feature doesn't fit with Godot's methodology as specified in the documentation: https://docs.godotengine.org/en/stable/about/faq.html#why-does-godot-aim-to-keep-its-core-feature-set-small

@Ezequias-Rodrigues
Copy link
Author

Well, one can say that you can implement this feature with addons or scripts, but imho it's so convoluted, like, why do i need to use physics or create another function that checks for inputs to pick mouse events in a Sprite2D when the engine code already provides the base for this system? It's also not quite intuitive why this system won't affect canvas items but is present in controls.

@404Fox
Copy link

404Fox commented Mar 2, 2026

The use case is that arbitrary shapes/sprites that are already in your scene can react to the mouse. For some this will mean that less nodes are used and it would replace boilerplate of trying to make such nodes mouse-reactive.
The binary size may grow a fraction of a kilobyte in exchange for cutting out boilerplate and streamlining designs in projects, a worthwhile trade-off. You could even build the engine without Control nodes and instead just use Polygon/Sprite for input too, and cut your build that way.

Also as someone that never heard the term "mouse picking" until today, is this not where mouse_filter ignore/pass/stop should be?

@Ezequias-Rodrigues
Copy link
Author

Ezequias-Rodrigues commented Mar 4, 2026

If i understood your question correctly, yes, but the mouse filter afaik is not present in other canvas items, and being honest with you, i forgot about these filters and just used the default input flow with a toggleable variable. Should i implement these filters?

@Ezequias-Rodrigues Ezequias-Rodrigues requested a review from a team as a code owner March 5, 2026 00:03
@ziDritz
Copy link

ziDritz commented Mar 9, 2026

Hey! Just passing by to say that I needed to implement that for my game (for AnimatedSprite2D), and I would love to have mouse interaction with sprites (if it does make sens with the engine)

https://forum.godotengine.org/t/on-click-event-with-animated-sprite-2d/134584?u=zidritz

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants